;;   manifold chunks routines
;;====================================================================
;; chunks.inc procedures list:
;;  delete_chunk
;;  detect chunks
;;  invert_normals_ch
;;  mirror chunk
;;  opt_chunks
;;  opt_chunks_th
;;  sort_chunks
mirror_chunk:
; in : eax - chunk no to mirror
                push   ebp
                mov    ebp,esp
                .cur_ch     equ dword[ebp-4]
                .pcv        equ dword[ebp-8]
                .tri_in_ch  equ dword[ebp-12]
                .tri_offset equ dword[ebp-16]
                .new_ptsI2  equ dword[ebp-20]
                .new_ptsI   equ dword[ebp-24]
                .vert_cnt   equ dword[ebp-28]
                .new_vert   equ dword[ebp-32]
                .new_tris   equ dword[ebp-36]
                .mxx        equ [ebp-80]
                cmp       eax,[chunks_count]
                jg        .end

                push      eax        ; cur ch
                push      [points_count_var]
                mov       esi,[chunks_ptr]
                mov       ecx,[triangles_count_var]
                cld
                xor       edx,edx
                xchg      ebx,eax
            .lab1:
                lodsw
                cmp       bx,ax
                je        @f
                loop      .lab1
            @@:
                inc       edx
                mov       edi,esi
                sub       edi,[chunks_ptr]
            .lab2:
                lodsw
                cmp       bx,ax
                je        @f
                loop      .lab2
                jmp       .en1
            @@:
                inc       edx
                loop     .lab2
            .en1:
                push    edx     ; tri in ch
                inc     edx
                ;  (edi-2)/2 - tris cnt to skip
                sub     edi,2
                add     edi,edi
                lea     edi,[edi*3]
                add     edi,[triangles_ptr]
                push    edi        ;  ebx - triangles offset in triangles list
                mov     ebx,edx ;ecx
                imul    ebx,12     ;  ebx - max vertices (size in mem) used in current chunk
                add     ebx,200
                malloc  ebx        ; vert index1
                push    eax
                malloc  ebx
                push    eax        ; vert index2
                cld
                mov     ecx,.tri_in_ch
                mov     esi,.tri_offset
                mov     edi,.new_ptsI2
                lea     ecx,[ecx*3]
                push    ecx
                rep     movsd
                mov      esi,.new_ptsI2
                mov      edi,.new_ptsI
                pop      ecx
                call     sort_hybrid_dd
                ; calc distinc verts count in cur chun
                mov      esi,.new_ptsI2
                mov      edi,.new_ptsI
                mov      ecx,.tri_in_ch
                lea      ecx,[ecx*3]
                xor      edx,edx
                mov      edx,1
                cld
            .bb1a:
                lodsd
                mov      ebx,[esi]
                cmp      ebx,eax
                jne      @f
                loop     .bb1a
                jmp      .fin1a
            @@:
                stosd
                inc      edx
                loop     .bb1a
            .fin1a:
                or       eax,-1
                stosd    ; end mark
                push     edx
                ;  edx - uniqe verts count in chunk
                ; .new_ptsI - sorted uniqe verts
                add      edx,.pcv  ;[points_count_var]
                imul     edx,12
                add      edx,128
                malloc   edx
                push     eax   ;new verts  whole list
                cvtdq2ps   xmm3,[xxadd]
                andps      xmm3,[zero_hgst]
                mov        esi,[points_rotated_ptr]
                mov        edi,eax
                mov        ecx,.pcv  ;[points_count_var]
            @@:
                movups     xmm0,[esi]
                subps      xmm0,xmm3
                movups     [edi],xmm0
                add        esi,12
                add        edi,12
                loop       @b
                cld
                ;compute new  tri list, fill new verts list with new positions
                mov    eax,1 shl 31
                movd   xmm2,eax      ; x axis related mirror
                ; it easy posible do y and z
                ;   shufps xmm2,xmm2,11110011b
                mov     esi,.tri_offset  ;.new_ptsI ;.tri_in_ch
                mov     ecx,.tri_in_ch
                lea     ecx,[ecx*3]
                mov     edi,.new_ptsI2
            .bbc:
                push    ecx
                lodsd
                cmp     eax,.pcv          ;[points_count_var]
                jnbe    .nxc
                push    edi
                mov     edx,eax
                imul    edx,12
                add     edx,.new_vert    ; [points_rotated_ptr]
                movups  xmm0,[edx]
                xorps   xmm0,xmm2        ; negate x cooef
                mov     edi,.new_ptsI
                or      ecx,-1           ;.vert_cnt  ;.tri_in_ch
                repne   scasd
                sub     edi,.new_ptsI
                shr     edi,2
                dec     edi
                mov     eax,edi
                pop     edi
                add     eax,.pcv         ;[points_count_var]
                mov     edx,eax
                imul    edx,12
                add     edx,.new_vert
                movlps  [edx],xmm0       ; new vertex in new_vert lst
                movhlps xmm0,xmm0
                movss   [edx+8],xmm0
                stosd                   ; new vert index in .new_ptsI2 list
            .nxc:
                pop     ecx
                loop    .bbc
                ; new_ptsI2 - new chunk triangles
                mfree  .new_ptsI
                mov     ebx,.tri_in_ch
                add     ebx,[triangles_count_var]
                imul    ebx,12
                add     ebx,120
                malloc  ebx
                push    eax   ; new_tris - whole list of triangles
                cld
                mov     edi,eax
                mov     ecx,[triangles_count_var]
                mov     esi,[triangles_ptr]
                lea     ecx,[ecx*3]
                rep     movsd
                mov     esi,.new_ptsI2
                mov     ecx,.tri_in_ch
                lea     ecx,[ecx*3]
                rep     movsd
                mfree   .new_ptsI2
                mfree   [points_r_ptr]
                mfree   [triangles_ptr]
                mov     eax,.tri_in_ch
                mov     ebx,.vert_cnt
                add     [triangles_count_var],eax
                add     [points_count_var],ebx
                push    .new_tris
                pop     [triangles_ptr]
                sub      esp,60
                mov      esi,matrix
                lea      edi,.mxx
                call     reverse_mx_3x3
                mov      esi,.new_vert
                mov      edi,.new_vert
                mov      ecx,[points_count_var]
                lea      ebx,.mxx
                call     rotary
                push     .new_vert
                pop      [points_r_ptr]
              .end:
                mov     esp,ebp
                pop     ebp
                ret
 ;==============================================================
 opt_chunks:
                push     ebp
                mov      ebp,esp
                sub      esp,60
             ;   .th_no      equ dword[ebp-4]
                .cur_ch     equ dword[ebp-8]
                .a_vert_cnt equ dword[ebp-12]
                .ch_ptr     equ dword[ebp-16]
                .tri_old    equ dword[ebp-20]
                .tri_offset equ dword[ebp-24]
                .new_ptsI2  equ dword[ebp-28]
                .new_ptsI   equ dword[ebp-32]
                .tri_count  equ dword[ebp-36]
                .c_vert_cnt equ dword[ebp-40]
                .tri_in_chOPT equ dword[ebp-44]
                .new_normals  equ dword[ebp-48] ; \
                .new_pn       equ dword[ebp-52] ;  > dont change order
                .points1_ptr  equ [ebp-56]      ; /
                cmp    [chunks_count],1
                je     .end
                push   [chunks_ptr]
                pop    .ch_ptr
                push   [triangles_ptr]
                pop    .tri_old
                mov    ecx,[triangles_count_var]
                mov    .tri_count,ecx
                ; find greatest in size chunk
                mov    esi,.ch_ptr
            ;    mov    ecx,.tri_count
                cld
                xor    edx,edx
                xor    ebx,ebx
            .lab1:
                lodsw
                cmp    ax,[esi]
                je     @f
                cmp    ebx,edx
                cmovb  ebx,edx
                xor    edx,edx
                loop   .lab1
                jmp    .en1
            @@:
                inc    edx
                loop   .lab1
            .en1:
                mov    [greatest_chunk],ebx
                add     ebx,30
                imul    ebx,12
                malloc  ebx
                mov     .new_ptsI,eax
                malloc  ebx
                add     ebx,ebx
                movd    xmm0,ebx
                mov     .new_ptsI2,eax
                xor    eax,eax
                mov    ebx,1
                mov    .a_vert_cnt,eax      ; vertex count accumulator
                mov    .cur_ch,ebx
                mov    edi, .ch_ptr ;[chunks_ptr]
                mov    dx,[edi]
                or     dx,dx
                cmove  dx,bx
                mov    [edi],bx
            .Chunks_LOOP:
                cld
                xor    eax,eax
                mov    .c_vert_cnt,eax
                mov    edi,.ch_ptr   ;[chunks_ptr]
                mov    ecx,.tri_count ;[triangles_count_var]
                mov    eax,.cur_ch
                repne  scasw
                sub    edi,2
                mov    esi,edi             ; edi - start of curr chunk
                push   edi
                sub    esi,.ch_ptr
                ;  (esi-2)/2 - tris cnt to skip
                imul   esi,6
                add    esi,.tri_old        ; [triangles_ptr]
                mov    .tri_offset,esi
                ;  esi - val to skip
                add    edi,2
                or     ecx,-1
                mov    eax,.cur_ch
                repe   scasw
                pop    ebx
                sub    edi,ebx
                sub    edi,2
                shr    edi,1
                ;  edi tri in curr ch
                mov    .tri_in_chOPT,edi
                ;  esi - cur tri offset
                cld
                mov    ecx,edi ;.tri_in_ch
                mov    esi,.tri_offset
                mov    edi,.new_ptsI2
                lea    ecx,[ecx*3]
                push   ecx
                rep    movsd
                mov    esi,.new_ptsI2
                mov    edi,.new_ptsI
                pop    ecx
                call   sort_hybrid_dd
                ;  calc distinc verts count in curr chun
                mov      esi,.new_ptsI2
                mov      edi,.new_ptsI
                mov      ecx,.tri_in_chOPT
                lea      ecx,[ecx*3]
                xor      edx,edx
                ;  mov       edx,1
                cld
            .bb1a:
                lodsd
                mov      ebx,[esi]
                cmp      ebx,eax
                jne      @f
                loop     .bb1a
                jmp      .fin1a
            @@:
                stosd
                inc      edx
                loop     .bb1a
            .fin1a:
                mov      .c_vert_cnt,edx      ; curr
                mov      ecx,.a_vert_cnt
                add      .a_vert_cnt,edx      ; accum
                mov      eax,.cur_ch
                mov      ebx,eax
                shl      ebx,4
                add      ebx,[chunks_desc_ptr]
                mov      [ebx+4],edx          ; fill aprpopiate field data in chunks_desc struct
                mov      [ebx+8],ecx          ; verts offset
                ; no triangle work ??
                ;       mov      ecx,[ebx-16]      ; prev count
                ;       add      ecx,[ebx-4]       ; prev offs
                ;       mov      [ebx+12],ecx      ; curr offs
                       mov      ecx,.tri_in_chOPT
                       mov      [ebx],ecx         ; curr count
                inc      eax
                mov      .cur_ch,eax
                cmp      eax,[chunks_count] ;.ch_cnt
                jle      .Chunks_LOOP
                ; [chunks_desc_ptr] -  struct should have (for every chunk)
                ;     + 0 - count of tris in chunk
                ;     + 4 - count of vertices in chunk
                ;     + 8 - vertices offset
                ;     + 12 - triangles_offset
                mfree    .new_ptsI
                mfree    .new_ptsI2
                mov      ebx,[points_count_var]
                add      ebx,100
                imul     ebx,12
                malloc   ebx
                mov      .points1_ptr,eax
                malloc   ebx
                mov      .new_pn,eax
                mov      ebx,.tri_count
                add      ebx,100
                imul     ebx,12
                malloc   ebx
                mov      .new_normals,eax
                movups   xmm0,.points1_ptr
                mov      eax,thread_params_ch
                movups   [eax],xmm0
                cmp      [points_count_var],10000
                jb       @f
                cmp      [chunks_count],8
                ja       .th_ver
            @@:
                mov      byte[eax+12],'s'      ; single thread
                or       ebx,-1
                call     opt_chunks_th
                jmp      .single_t
            .th_ver:
                mov      byte[eax+12],'t'      ; threaded ver
                mov      eax,opt_chunks_th
                xor      edx,edx
                mov      ecx,4                 ; thrd count
                ; in eax  - proc-th adress
                ;    edx -  param bitewise 'and' with param passed to proc_th
                call     call_thread
            .single_t:
                mov      ebx,[chunks_count]
                shl      ebx,4
                add      ebx,[chunks_desc_ptr]
                mov      ecx,[ebx-16]      ; prev count
                add      ecx,[ebx-4]       ; prev offs
                mov      [ebx+12],ecx      ; curr offs
                mov      ecx,.tri_in_chOPT
                mov      [ebx],ecx         ; curr count
                mfree    [points_r_ptr]
                mfree    [triangles_normals_ptr]
                mfree    [points_normals_ptr]
                push     dword .points1_ptr
                pop      [points_r_ptr]
                push     .new_normals
                pop      [triangles_normals_ptr]
                push     .new_pn
                pop      [points_normals_ptr]
            .end:
                mov      esp,ebp
                pop      ebp
                ret
;==============================================================
opt_chunks_th:
;  optimize chunks
;  proc should do:
;  every chunk has only its own coninous fragment of vertices list
;  localised in standard chunks order (like triangles list), so
;  new_points, new_vertices_norm, tris_norm, ptsi1 and 2
;  th ver:
;           if [thread_params_ch+12] = 't'
;           ebx   =   th no
;
;           mov       eax,[thread_params_ch]
;           {eax]    - ptr to points_r
;           [eax+4]  - ptr to points normals
;           [eax+8]  - ptr to tris normals
;  out:
;           renewed structures
                prompt       prompt_opt
                push         ebp
                mov          ebp,esp
                .points1_ptr  equ dword[ebp-4]
                .new_pn       equ dword[ebp-8]   ; new points nom
                .new_normals  equ dword[ebp-12]
                .new_ptsI2    equ dword[ebp-16]
                .new_ptsI     equ dword[ebp-20]
                .nor_cur_ptr  equ dword[ebp-24]
                .cur_ch       equ dword[ebp-28]
                .c_vert_cnt   equ dword[ebp-32]
                .a_vert_cnt   equ dword[ebp-36]
                .tri_in_chOPT equ dword[ebp-40]
                .tri_offset   equ dword[ebp-44]
                .cross        equ dword[ebp-48]
                .sort         equ dword[ebp-52]
                .ch_ptr       equ dword[ebp-56]
                .ch_cnt       equ dword[ebp-60]
                .tnor_old                      equ dword[ebp-124]
                .triangles_normals_rotated_ptr equ dword[ebp-120]
                .points_normals_ptr            equ dword[ebp-116]
                .points_count_var      equ dword[ebp-112]
                .tri_count             equ dword[ebp-108]
                .pts_r                 equ dword[ebp-104]
                .tri_old               equ dword[ebp-100]
                .points_rotated_ptr    equ dword[ebp-96]
                .pnor_old              equ dword[ebp-92]
                .chunks_desc_ptr       equ dword[ebp-88]
                .th_no                 equ [ebp-84]
                .thM                   equ byte[ebp-79] ; thread mark s = single, t = threaded
                .tmp_cnt               equ [ebp-64]
                sub      esp,140
                mov      .th_no,ebx
                cmp      [chunks_count],1
                je       .end_ch
                pushad
                mov      eax,[greatest_chunk]
                add      eax,30
                imul     eax,12
                malloc   eax
                push     eax
                mov      .new_ptsI,eax    ; mem for pivot lists
                pop      eax
                malloc   eax
                mov      .new_ptsI2,eax
                ; [chunks_desc_ptr] structure
                push     esi edi                        ; and alloc 'global' areas for:
                lea      esi,[triangles_normals_ptr]    ; 1. points_r_ptr
                lea      edi,.tnor_old                  ; 2. triangles_normals_ptr
                mov      ecx,9                          ; 3. points_normals_ptr
                cld                                   ; 4. eventually  - area for tris
                rep      movsd
                pop      edi esi
                push     [chunks_ptr]
                push     [chunks_count]
                push     [chunks_desc_ptr]
                pop      .chunks_desc_ptr
                pop      .ch_cnt
                pop      .ch_ptr
                mov      eax,.new_normals
                mov      .nor_cur_ptr,eax
                mov      .cross,cross_reg
                mov      .sort,sort_hybrid_dd
                mov      ebx,thread_params_ch
                mov      eax,[ebx]
                mov      .points1_ptr,eax
                mov      eax,[ebx+4]
                mov      .new_pn,eax
                mov      eax,[ebx+4]
                mov      .new_normals,eax
                mov      .nor_cur_ptr,eax
                mov      al,[ebx+12]
                mov      .thM,al
                cmp      al,'t'
                jne      .no_t
                mov      eax,.ch_cnt
                shr      eax,2
                mov      edx,eax
                imul     eax,.th_no
                mov      ecx,eax
                add      ecx,edx
                inc      eax
                mov      .cur_ch,eax
                ;        add     ecx,2
                ;        cmp      .th_no,3
                mov      .ch_cnt,ecx
                xor     ecx,ecx
                mov     ebx,.ch_cnt
                and     ebx,11b
                inc     ebx
                inc     ebx
                cmp     byte .th_no,3
                cmove   ecx,ebx
                add     .ch_cnt,ecx
                shl     eax,4
                add     eax,.chunks_desc_ptr
                mov     eax,[eax+8]
                ;     xor     ebx,ebx
                ;     mov     ecx,3
                ;     cmp     byte .th_no,3
                ;     cmove   ebx,ecx
                ;     add     eax,ebx
                mov    .a_vert_cnt,eax
                jmp    .Chunks_LOOP
            .no_t:
                xor    eax,eax
                mov    ebx,1
                mov    .a_vert_cnt,eax      ;  vertex count accumulator
                mov    .cur_ch,ebx          ;  .ch_cnt
                mov    ecx,.ch_ptr          ;  .cur_ch
                mov    dx,[ecx]             ;  set properly above values
                or     dx,dx
                cmove  dx,bx
                mov    [ecx],bx

            .Chunks_LOOP:
                cld
                mov    edi,.ch_ptr
                mov    ecx,.tri_count
                mov    eax,.cur_ch
                repne  scasw
                sub    edi,2
                mov    esi,edi             ; edi - start of curr chunk
                push   edi
                sub    esi,.ch_ptr
                ;  (esi-2)/2 - tris cnt to skip
                imul   esi,6
                add    esi,.tri_old        ; [triangles_ptr]
                mov    .tri_offset,esi
                ;  esi - val to skip

            ;    mov    eax,.cur_ch
            ;    shl    eax,4
            ;    add    eax,.ch_ptr
            ;    mov    edi,[eax]

                add    edi,2
                or     ecx,-1
                mov    eax,.cur_ch
                repe   scasw
                pop    ebx
                sub    edi,ebx
                sub    edi,2
                shr    edi,1
                ;  edi tri in curr ch
                mov    .tri_in_chOPT,edi
                ;         mov    eax,.cur_ch
                ;         shl    eax,4
                ;         add    eax,.chunks_desc_ptr
                ;         mov    edi,[eax]
                ;         mov    .tri_in_chOPT,edi
                ;         mov    esi,[eax+12]
                ;         imul   esi,12
                ;         add    esi,.tri_old
                ;         mov    .tri_offset,esi
                ;  esi - cur tri offset
                cld
                lea     edi,[edi*3]
                mov    .tmp_cnt,edi
                mov     ecx,edi ;.tri_in_ch
                mov     esi,.tri_offset
                mov     edi,.new_ptsI2
                push    ecx
                rep     movsd
                mov     esi,.new_ptsI2
                mov     edi,.new_ptsI
                pop     ecx
                call   .sort  ; sort_hybrid_dd
                ;  calc distinc verts count in curr chun
                mov     esi,.new_ptsI2
                mov     edi,.new_ptsI
                mov     ecx,.tri_in_chOPT
                lea     ecx,[ecx*3]
                xor     edx,edx
                ;  mov       edx,1
                cld
            .bb1a:
                lodsd
                mov     ebx,[esi]
                cmp     ebx,eax
                jne     @f
                loop    .bb1a
                jmp     .fin1a
            @@:
                stosd
                inc     edx
                loop    .bb1a
            .fin1a:
                mov      .c_vert_cnt,edx  ; curr
                ;  edx - uniqe verts count in curr chunk
                ; .new_ptsI - sorted uniqe verts
                xor     ecx,ecx
                mov     esi,.new_ptsI
            .llb:
                lodsd
                imul    eax,12
                push    eax
                add     eax,.pts_r
                mov     edi,.a_vert_cnt
                add     edi,ecx
                imul    edi,12
                push    edi
                add     edi,.points1_ptr
                xchg    eax,esi
                movsd             ; transfer vertices
                movsd
                movsd
                xchg    eax,esi
                pop     edi eax
                add     edi,.new_pn      ; new normal position
                add     eax,.points_normals_ptr   ;nor_tmp
                xchg    esi,eax
                movsd             ; transfer points normals
                movsd
                movsd
                xchg    esi,eax
                inc     ecx
                cmp     ecx,.c_vert_cnt
                jnz     .llb
                cld
                mov     esi,.new_ptsI    ; esi - list with uniqe old indices of verts
                mov     ecx,.tmp_cnt
                shr     ecx,3
                inc     ecx
                mov     .tmp_cnt,ecx
                xor     ecx,ecx
                mov     edi,.tri_offset
                pcmpeqd xmm1,xmm1
            .lloo:
                push    ecx
                mov     edx,ecx
                add     edx,.a_vert_cnt  ; new index to xchg in edx
                lodsd                    ; load old index into eax
                mov     ebx,.new_ptsI2
                mov     ecx,.tmp_cnt
                mov     edi,.tri_offset
                movd    xmm0,edx
                movd    xmm2,eax
                shufps  xmm0,xmm0,0
                shufps  xmm2,xmm2,0
            .llo:
                movups  xmm6,[edi]
                movups  xmm7,[edi+16]
                pcmpeqd xmm6,xmm2  ; xm6 = 1st mask
                pcmpeqd xmm7,xmm2
                movaps  xmm5,xmm6
                movaps  xmm4,xmm7
                xorps   xmm5,xmm1  ; xm5 = 2cond mask
                xorps   xmm4,xmm1
                andps   xmm5,[ebx]
                andps   xmm4,[ebx+16]
                andps   xmm6,xmm0
                andps   xmm7,xmm0
                por     xmm5,xmm6
                por     xmm4,xmm7
                movaps  [ebx],xmm5
                movaps  [ebx+16],xmm4
                add     ebx,32
                add     edi,32
                loop    .llo
                pop     ecx
                inc     ecx
                cmp     ecx,.c_vert_cnt
                jnz     .lloo
                mov      edi,.tri_offset
                mov      ecx,.tri_in_chOPT
                lea      ecx,[ecx*3]
                mov      esi,.new_ptsI2
                rep      movsd                ; renew triangles indexes list in curr chunk
                mov      ecx,.a_vert_cnt      ; offset
                mov      edx,.c_vert_cnt      ; curr
                add      .a_vert_cnt,edx      ; accum
                mov      eax,.cur_ch
                inc      eax
                mov      .cur_ch,eax
                cmp      eax,.ch_cnt
                jle      .Chunks_LOOP
                ;        mov      eax,[ebx-16]
                ;        add      eax,[ebx-4]     ; tiny fix of chunks desc list
                ;        mov      [ebx+12],eax
                ;   [chunks_desc_ptr] -  struct should have (for every chunk)
                ;                             + 0 - count of tris in chunk
                ;                             + 4 - count of vertices in chunk
                ;                             + 8 - vertices offset
                ;                             + 12 - triangles_offset
                cmp      byte .th_no,3
                je       @f
                cmp      .thM,'t'
                je       .en1
            @@:
                mov      ebx,.a_vert_cnt             ;
                mov      [points_count_var],ebx
            .en1:
                popad
                mfree   .new_ptsI2
                mfree   .new_ptsI
            .end_ch:
                mov      esp,ebp
                pop      ebp
                ret
;==============================================================
;======================================================================
sort_chunks:
; sort chunks, sort triangles, triangles normal vectors
                push   ebp
                mov    ebp,esp
                .ptr1            equ [ebp-4]
                .ptr2            equ [ebp-8]
                .points_r        equ [ebp-12]
                .tcv             equ [ebp-16]
                .tptr            equ dword[ebp-20]
                .chunks_struct   equ dword [ebp-24]
                .chunks_structEx equ [ebp-28]
                .was_used        equ [ebp-32]
                .cnt             equ [ebp-36]
                .accum_tris      equ [ebp-40]
                mov      ebx,[chunks_count]
                cmp      ebx,1
                je       .end_one
                pushad
                call     remove_non_tri
                popad
                mfree    [chunks_desc_ptr]
                mfree    [chunk_desc_Ex_ptr]
                mov      ebx,[triangles_count_var]
                add      ebx,150
                imul     ebx,12
                ;    mov      eax,[edges_count]
                ;    add      eax,15
                ;    shl      eax,3
                ;    cmp      eax,ebx
                ;    cmovna   eax,ebx
                malloc   ebx
                push     eax   ; ptr1
                malloc   ebx
                push     eax   ; ptr2
                push     [points_r_ptr]
                push     [triangles_count_var]   ; .tcv
                push     [triangles_ptr]
                sub      esp,40
                mov      esi,[chunks_ptr]
                mov      edi,.ptr1
                xor      ecx,ecx
                cld
            @@:
                ;make pivot table
                lodsw
                movzx    eax,ax
                stosd
                mov      eax,ecx
                stosd
                inc      ecx       ; tri no
                cmp      ecx,.tcv  ; [triangles_count_var]
                jnz      @b
                mov      esi,.ptr1
                mov      edi,.ptr2
                mov      ecx,.tcv
                call     sort_hybrid
                mov      esi,.ptr1
                mov      edi,.ptr2
                mov      ebx,[chunks_ptr]
                mov      ecx,.tcv
                cld
            @@:
                lodsd
                mov      [ebx],ax         ; renew chunks, triangles lists
                lodsd
                push     esi
                imul     eax,12
                add      eax,.tptr        ; [triangles_ptr]
                mov      esi,eax
                movsd
                movsd
                movsd
                pop      esi
                add      ebx,2
                loop     @b
                mov      esi,.ptr1        ; renew tri normals list
                mov      edi,.tptr
                mov      ebx,[triangles_normals_ptr]
                mov      ecx,.tcv         ; [triangles_count_var]
                cld
            @@:
                lodsd
                lodsd
                imul     eax,12
                add      eax,ebx
                xchg     esi,eax
                movsd
                movsd
                movsd
                xchg     esi,eax
                loop     @b
                ; do chunks struct, renew points, triangles list, so -
                ; -  vert indexes/indices in tri list. Rearanging  vertices list,
                ; sort according to every chunk - opt_chunks proc..
                mov      ebx,[chunks_count]
                shl      ebx,4
                add      ebx,200
                malloc   ebx
                mov      .chunks_struct,eax
                shl      ebx,2
                malloc   ebx
                mov      .chunks_structEx,eax      ; max, min, avg vertices
                ; in chunk
                ;   or       eax,-1
                ;   mov      .chunks_struct,eax
                ;   mov      ebx,[chunks_count]
                ;   cmp      ebx,1
                ;   je       .end
                mov      ebx,[points_count_var]
                add      ebx,300
                malloc   ebx
                mov      .was_used,eax
                mov      edi,eax
                xor      eax,eax
                mov      .cnt,eax
                mov      .accum_tris,eax
                mov      ecx,ebx
                sub      ecx,3
                shr      ecx,2
                rep      stosd
                mov      edi,.chunks_struct       ; make chunks stuct
                mov      esi,[chunks_ptr]         ; every dword - triangles count in chunk
                mov      ecx,.tcv                 ; [triangles_count_var]
                mov      edx,.ptr2                ; [triangles_ptr]
                cld
                lodsw
                inc      dword[edi]
                dec      ecx
                jz       .lab2
                mov      bx,ax
                xorps    xmm0,xmm0
                xorps    xmm1,xmm1
                ;  movss     .cnt,xmm0
            .lab1:
                lodsw
                cmp      bx,ax
                jne      .nx_1
                inc      dword[edi]
                push     eax
                push     ebx
                push     ecx
                mov      ecx,3
            .tri_lab:
                mov      eax,[edx]
                mov      ebx,eax
                add      ebx,.was_used
                cmp      byte [ebx],0
                jne      .f_1
                mov      byte [ebx],1
                imul     eax,12
                add      eax,.points_r
                movups   xmm1,[eax]
                maxps    xmm0,xmm1
                minps    xmm2,xmm1
            .f_1:
                add      edx,4
                loop    .tri_lab
                pop      ecx
                pop      ebx
                pop      eax
                loop     .lab1
                or       ecx,ecx
                jz       .lab2
            .nx_1:
                push    edx
                xorps   xmm0,xmm0
                xorps   xmm2,xmm2
                mov     edx,.accum_tris
                mov     [edi+12],edx   ; tri offset
                add     edx,[edi]
                mov     .accum_tris,edx
                pop     edx
                add     edi,16
                inc     dword .cnt
                xchg    ebx,eax
                loop    .lab1
            .lab2:
                ;   [chunks_desc_ptr]         + 0 - count of tris in chunk
                ;   struct should have:       + 4 - count of vertices in chunk
                ;   (for every chunk)         + 8 - vertices offset
                ;   call to opt_chunks        + 12 - triangles_offset
                ;   to fill this struct
            .end:
                mfree  .ptr1
                xor    eax,eax
                mov    .ptr1,eax
                mfree  .was_used
                mfree  [triangles_normals_ptr]
                push   .chunks_struct
                pop    [chunks_desc_ptr]
                push   dword .chunks_structEx
                pop    [chunk_desc_Ex_ptr]
                push    [triangles_ptr]
                pop     [triangles_normals_ptr]
                push    dword .ptr2
                pop     [triangles_ptr]
            .end_one:
                mov     esp,ebp
                pop     ebp
ret
;================================================================================
delete_chunk:
; in eax - chunks No to delete
; Need perform remove dead triangles and remove
; unused vertices at the end of process.
                mov    esi,[chunks_ptr]
                mov    ecx,[triangles_count_var]
                mov    edi,[triangles_ptr]
                xorps  xmm0,xmm0
                mov    bx,ax
                cld
                .nxx:
                lodsw
                cmp    bx,ax
                jne    @f
                movlps   [edi],xmm0
                movd   [edi+8],xmm0
            @@:
                add    edi,12
                loop   .nxx
ret
;============================================================
invert_normals_ch:
; invert sense of normal vectors of selected chunk;
; in eax - index number of selected chunk
                mov    esi,[chunks_ptr]
                mov    ecx,[triangles_count_var]
                mov    edi,[triangles_ptr]
                mov    bx,ax
                cld
                .nxx:
                lodsw
                cmp     bx,ax
                jne     @f
                movlps  xmm0,[edi]
                shufps  xmm0,xmm0,11100001b
                movlps  [edi],xmm0
            @@:
                add     edi,12
                loop    .nxx
ret
;=========================================================================
detect_chunks:
; make pivot table, sort, remove unused vertices, find chunks...
; in  - some global variables and
;   eax = 0 or 1 - export or non export some lists
;   ebx = 0x33333333  -> make only pivot table
; out:
; if eax = 0
;      ebx - chunks list ptr
;      ecx - chunks number
; if eax = 1 above and -
;      esi - tri_ch    ; vertices with triangles list
;      edi - t_ptr     ; pointers to tri_ch list
                push ebp
                mov  ebp,esp
                sub  esp,68
                .tri_ch         equ  dword[ebp-4]    ; tri chunks list ptr
                .chunks         equ  dword[ebp-8]    ; chunks ptreach tri chunk No. as word
                .endt           equ  dword[ebp-12]   ;
                .t_ptr          equ  dword[ebp-16]   ; pointers list
                .tri_ch1        equ  dword[ebp-20]   ;
                .up             equ  dword[ebp-24]   ; upload ptr
                .chmr           equ  dword[ebp-28]   ; bit mark list if tri stored
                .str            equ  dword[ebp-32]   ; store ptr
                .ltch1          equ  dword[ebp-36]   ; end of tri_ch1 ptr
                .ch_cnt         equ  dword[ebp-40]
                .cntt           equ  dword[ebp-44]
                .cc             equ  dword[ebp-48]
                .lsparam        equ  dword[ebp-52]
                .fix_mark       equ  dword[ebp-56]
                .endVptr        equ  dword[ebp-60]
                .pivot          equ  dword[ebp-64]
                .old_esp        equ  dword[ebp-68]
                mov     .lsparam,eax
                mov     .pivot,ebx
                call    remove_non_tri
                mov     .fix_mark,0
                mov     eax,[triangles_ptr]
                mov     ebx,[points_r_ptr]
                mov     ecx,[triangles_count_var]
                mov     edx,[points_count_var]
                call    remove_unused_vertices
                mov     [points_count_var],ecx
                prompt  prompt_det_chunks1 ; macro
                mov     ebx,[triangles_count_var]
                shl     ebx,3
                lea     ebx,[ebx*3]    ; 8 * 3 - 24 bytes ?
                add     ebx,65536
                malloc  ebx
                mov     .tri_ch,eax
                malloc  ebx
                mov     .tri_ch1,eax
                mov     ebx,[triangles_count_var]
                shl     ebx,4
                add     ebx,3000
                malloc  ebx
                mov     .t_ptr,eax
                mov     ebx,.pivot
                cmp     ebx,0x33333333
                je      .no_a
                cmp     ebx,0x33
                je      .no_a
                mov     ebx,[triangles_count_var]
                shl     ebx,1
                add     ebx,20
                malloc  ebx
                mov     .chunks,eax   ; each tri chunk No. as word
                shr     ebx,4
                malloc  ebx
                mov     .chmr,eax     ; chunks mark if bit is set - tri was used
                ;  .ag: ; again
                ;   mov     .fix_mark,0
            .ag:
                call    remove_non_tri
                mov     edi,.chmr
                xor     eax,eax
                mov     ecx,[triangles_count_var]
                cld
                shr     ecx,2 + 3
                inc     ecx
                rep     stosd
            .no_a:
                mov     eax,[points_count_var]
                imul    eax,12
                add     eax,[points_r_ptr]
                mov     .endVptr,eax
                ; make pivot table
                mov     edi,.tri_ch
                mov     esi,[triangles_ptr]
                xor     ecx,ecx
                cld
            @@:                      ; interlaved vert index, triangle index
                movsd
                mov     eax,ecx
                stosd
                movsd
                stosd
                movsd
                stosd
                inc     ecx
                cmp     ecx,[triangles_count_var]
                jnz     @b
                ; qsort
                mov     esi,.tri_ch
                mov     edi,.tri_ch1
                mov     ecx,[triangles_count_var]
                lea     ecx,[ecx*3]
                call    sort_hybrid
                mov     esi,.tri_ch
                mov     edi,esi
                mov     eax,[triangles_ptr]
                mov     ebx,[points_r_ptr]
                mov     ecx,[triangles_count_var]
                mov     edx,[points_count_var]
                call    remove_unused_vertices
                mov     [points_count_var],ecx
                mov     ecx,[triangles_count_var]
                lea     ecx,[ecx*3]
                mov     esi,ecx
                shl     esi,3
                add     esi,.tri_ch
                mov     .endt,esi
                prompt  prompt_det_chunks ; sec stage
            .do_ch:
                ;make t_ptr  - table with pointers/adresses
                mov    ecx,[points_count_var]
                mov    esi,.tri_ch
                mov    edi,.t_ptr
                mov    ebx,ecx
                mov    [edi],esi
                add    edi,4
                dec    ecx
                jz     .dn33
            .pt:
                mov    eax,[esi]        ; [esi]   - vert ind
                add    esi,8
                movss  xmm0,[esi+4]
                cmp    eax,[esi]        ; [esi+4] - tri ind
                je     @f
                mov    [edi],esi       ;  [edi] - pointer
                add    edi,4
                dec    ecx
                jz     .dn33
            @@:
                cmp    esi,.endt
                jb     .pt
            .dn33:
                mov    ebx,.pivot
                cmp    ebx,0x33333333
                je     .end2_piv
                cmp    ebx,0x33
                je     .end2_piv
                mov    edi,.t_ptr
                mov    ecx,[triangles_count_var]
                ;  mov     ebx,ecx
                ;  imul    ebx,12
                ;  add     edi,ebx
                ;  or      eax,-1
                ;  cld
                ;  stosd    ; mark
                ; each dword position in .t_ptr list - adress of corresponding
                ; triangles indexes, each triangles from such index contains this vertice
                ; search for chunks
                mov     eax,ecx     ; [triangles_count_var]
                mov     .cntt,eax   ; temp help cnt
                xor     ecx,ecx
                mov     .cc,ecx
                mov     esi,[triangles_ptr]
                mov     edi,.tri_ch1
                imul    eax,12
                shl     eax,3
                add     eax,edi
                mov     .ltch1,eax
                mov     .up,esi
                mov     .str,edi
            .lb1:
                ;  mov     edi,.str   ;           ; nx chunk
                cmp     edi,.ltch1
                jnb     .endl                  ; nb
                mov     .str,edi
                mov     eax,.cc
                mov     edx,.cc
                inc     .cc
                cmp     edx,[triangles_count_var]
                jz      .endl
                shr     eax,3
                and     edx,111b
                add     eax,.chmr
                xor     ebx,ebx
                bt      [eax],edx            ; mark
                jc      @f                   ; tri was stored
                inc     ecx
                or      ebx,1b
                mov     esi,.up
                movups  xmm0,[esi]
                movups  [edi],xmm0
                add     .str,12
            @@:
                add     .up,12
                or      ebx,ebx
                jz      .lb1
            .lb2:
                mov     eax,[edi]
                mov     edx,[edi]           ; edx - vert ind
                shl     eax,2
                add     eax,.t_ptr
                mov     eax,[eax]           ; [eax] -   t ptr
                or      eax,eax
                jz      .endl
            .nxt:
                mov     esi,[eax+4]
                mov     ebx,[eax+4]
                shr     esi,3
                and     ebx,111b
                add     esi,.chmr
                bts     [esi],ebx          ; mark
                jc      @f                 ; tri was stored
                dec     .cntt
                je      .endl
                mov     esi,[eax+4]        ; [eax+4] - tri ind
                add     esi,esi
                add     esi,.chunks
                mov     [esi],cx
                mov     esi,[eax+4]
                imul    esi,12
                add     esi,[triangles_ptr]
                movups  xmm0,[esi]
                mov     esi,.str
                movups  [esi],xmm0
                add     .str,12
            @@:
                add     eax,8
                cmp     edx,[eax]
                je      .nxt
                add     edi,4
                cmp     edi,.str
                jne     .lb2
                jmp     .lb1
            .endl:
                mov     .ch_cnt,ecx
            .end:
                cmp     .lsparam,1
                je      .ff1
                mfree   .t_ptr
                mfree   .tri_ch
            .ff1:
                mfree   .chmr
                mov      ebx,.chunks
            .end2_piv:
                mfree    .tri_ch1
                cmp      .pivot,0x33333333
                je       .ff2
                mov      ebx,.chunks
                mov      ecx,.ch_cnt
                jmp      .en2
            .ff2:
                or       ebx,-1
                or       ecx,-1
            .en2:
                mov      esi,.tri_ch
                mov      edi,.t_ptr
                cls    ; macro
                mov      esp,ebp
                pop      ebp
                ret
;==============================================================